<!doctype html>
<html xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <title>葡萄藤PPT</title>

    <link rel="stylesheet" href="../css/reveal/reveal.css">

    <!-- PPT主题，可以在/css/reveal/theme/中选择其他主题，目前暂时只能使用该模板 -->
    <link rel="stylesheet" href="../css/reveal/theme/ptt.css">

    <!-- syntax highlighting 代码高亮主题 -->
    <link rel="stylesheet" href="../lib/reveal/css/zenburn.css">

    <!-- 打印和PDF输出样式 -->
    <script>
        var link = document.createElement('link');
        link.rel = 'stylesheet';
        link.type = 'text/css';
        link.href = window.location.search.match(/print-pdf/gi) ? '../css/reveal/print/pdf.css' : '../css/reveal/print/paper.css';
        document.getElementsByTagName('head')[0].appendChild(link);
    </script>
</head>
<body>
<img src="../img/demo/logo.png" alt="" usemap="#pttmap" class="base-logo">
<map name="pttmap">
    <area shape="rect" coords="0,0,276,58" href="http://www.jnshu.com" alt="" target="_blank"/>
</map>
<div class="reveal">
    <div class="slides">
        <section>
            <h3>【JS-05】前端跨域问题有哪些常用的解决方式？</h3>
            <p>分享人：梁耀</p>
        </section>
        <section>
            <p>目录</p>
            <p>1.背景介绍</p>
            <p>2.知识剖析</p>
            <p>3.常见问题</p>
            <p>4.解决方案</p>
            <p>5.编码实战</p>
            <p>6.扩展思考</p>
            <p>7.参考文献</p>
            <p>8.更多讨论</p>
        </section>
        <section>
            <h3>1.背景介绍</h3>
        </section>
        <section>
            <section>
                理解跨域首先必须要了解同源策略。同源策略是浏览器上为安全性考虑实施的非常重要的安全策略。
            </section>

            <section>
                <p style="text-align: left;">
                    什么是同源政策？
                </p>
                <p>
                    浏览器的同源策略，限制了来自不同源的"document"或脚本，对当前"document"读取或设置某些属性。
                    从一个域上加载的脚本不允许访问另外一个域的文档属性。
                    举个例子：
                    比如一个恶意网站的页面通过iframe嵌入了银行的登录页面（二者不同源），如果没有同源限制，恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。
                </p>
            </section>
            <section>
                <p>
                    设想这样一种情况：A网站是一家银行，用户登录以后，又去浏览其他网站。如果其他网站可以读取A网站的 Cookie，会发生什么？
                    很显然，如果 Cookie 包含隐私（比如存款总额），这些信息就会泄漏。更可怕的是，Cookie 往往用来保存用户的登录状态，
                    如果用户没有退出登录，其他网站就可以冒充用户，为所欲为。因为浏览器同时还规定，提交表单不受同源政策的限制。
                    由此可见，"同源政策"是必需的，否则 Cookie 可以共享，互联网就毫无安全可言了。
                </p>
                <p>
                    1995年，网景公司将同源策略这一安全策略引入浏览器，规定不同的‘域’之间的数据相互不可访问。
                </p>
            </section>
            <section>
                <p >
                    什么算是同源？
                </p>
                <p>
                    URL由协议、域名、端口和路径组成，如果两个URL的协议、域名和端口相同，则表示他们同源。
                </p>
                <p>
                    举例来说，http://www.example.com/dir/page.html这个网址，协议是http://，
                    域名是www.example.com，端口是80（默认端口可以省略）。它的同源情况如下：
                </p>
                <p>
                    http://www.example.com/dir2/other.html：同源<br>
                    http://example.com/dir/other.html：不同源（域名不同）<br>
                    https://www.example.com/dir/other.html：不同源（协议不同）<br>
                    http://www.example.com:81/dir/other.html：不同源（端口不同）
                </p>
                <p>
                    请求不同‘源’的数据就算是跨域。
                </p>
            </section>
        </section>

        <section>
            <h3>2.知识剖析</h3>
        </section>
        <section>
            <section>
                <p >
                    实现跨域的常见方法有以下几种
                </p>
                <p >
                    1.JSONP跨域<br>
                    2.nginx反向代理<br>
                </p>
            </section>
            <section>
                <p >
                    1.JSONP跨域<br>
                    JSON(JavaScript Object Notation)和JSONP(JSON withPadding)虽然只有一个字母的差别，其实他们根本不是一回事儿：<br>
                    JSON是一种数据交换格式，而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。<br>
                    我们拿谍战片来打个比方，JSON是地下党们用来书写和交换情报的“暗号”，而JSONP则是把用暗号书写的情报传递给自己同志时使用的接头方式。<br>
                    一个是描述信息的格式，一个是信息传递双方约定的方法。</p>
            </section>
            <section>
                <p >
                    Ajax直接请求普通文件存在跨域无权限访问的问题，只要是跨域请求，一律不准；
                    不过，Web页面上调用js文件时则不受是否跨域的影响（不仅如此，我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力，
                    比如（/script/、/img、/iframe/）；
                    恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据，更妙的是JSON还被js原生支持，
                    所以在客户端几乎可以随心所欲的处理这种格式的数据；
                </p>
            </section>
            <section>
                <p>

                    这样子解决方案就呼之欲出了，web客户端通过与调用脚本一模一样的方式，
                    来调用跨域服务器上动态生成的js格式文件（一般以JSON为后缀），显而易见，服务器之所以要动态生成JSON文件，
                    目的就在于把客户端需要的数据装入进去。
                    客户端在对JSON文件调用成功之后，也就获得了自己所需的数据，剩下的就是按照自己需求进行处理和展现了，
                    这种获取远程数据的方式看起来非常像AJAX，但其实并不一样。
                  为了便于客户端使用数据，逐渐形成了一种非正式传输协议，人们把它称作JSONP，
                    该协议的一个要点就是允许用户传递一个callback参数给服务端，然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据，这样客户端就可以随意定制自己的函数来自动处理返回数据了。
                </p>
            </section>
            <section>
                <p>2.nginx反向代理<br></p>
                <p >
                    Nginx是一个HTTP服务器，可以将服务器上的静态文件（如HTML、图片）通过HTTP协议展现给客户端。
                    <br>反向代理服务器：客户端本来可以直接通过HTTP协议访问某网站应用服务器，网站管理员可以在中间加上一个Nginx，客户端请求Nginx，Nginx请求应用服务器，然后将结果返回给客户端，此时Nginx就是反向代理服务器。
                    <br>负载均衡:当网站访问量非常大，一台服务器已经不够用了。于是将同一个应用部署在多台服务器上，将大量用户的请求分配给多台机器处理。Nginx可以通过反向代理来实现负载均衡。
            </section>
        </section>
        <section>
            <h3>3.常见问题</h3>
            JSONP实现跨域原理?<br>
            nginx反向代理<br>

            代码中如何实现?
        </section>
        <section>
            <section>
                <h3>4.解决方案</h3>
                <p></p>
            </section>
            <section>
                <p >
                    JSONP实现跨域
                </p>
                <pre>
                    <code>
<script>
    /*
    * script标签不受同源策略限制
    * */
    function loadScript(url, fn) {
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.src = url;

        script.onload = script.onreadystatechange = function () {
            if (!this.readyState || this.readyState === 'loaded'
                || this.readyState === 'complete') {
                fn();
                script.onload = script.onreadystatechange = null;
            }
        };
        head.appendChild(script);
    }

    // 打印出数据
    window.baidu = {
        sug: function (data) {
            console.log(data);
        }
    };
    // 这是一个接口api，它会返回数据给你
    // http://suggestion.baidu.com/su?wd=w
    loadScript('http://suggestion.baidu.com/su?wd=w', function () {
        console.log('loading')
    });
</script>
                    </code>
                </pre>
            </section>
            <section>
                <p >
                    nginx反向代理
                </p>
                <pre>
                    <code>
	#task6-10
    server {
        listen       1080;//侦听1080端口
      	server_name  localhost;//域名

        location / {
            root   F:\\task\\JS5\\;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html =404;

        }
        location /carrots-admin-ajax/{
            proxy_pass http://120.92.4.89:10498/;
        }
	}
                    </code>
                </pre>
            </section>
        </section>
        <section>
            <section>
            <h3>6.扩展思考</h3>
            <h3>JSONP的优缺点</h3>
                <h3>其他实现跨域的方式</h3>
        </section>
        <section>
            <p>

                JSONP的优点是：</br>
                它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制；</br>
                它的兼容性更好，在更加古老的浏览器中都可以运行，不需要XMLHttpRequest或ActiveX的支持；</br>
                并且在请求完毕后可以通过调用callback的方式回传结果。

                JSONP的缺点则是：</br>
                它只支持GET请求而不支持POST等其它类型的HTTP请求；</br>
                它只支持跨域HTTP请求这种情况，不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
            </p>
        </section>
            <section>
                <p>CORS跨域资源分享<br>
                    WebSocket通信协议<br>
                    window.name<br>
                    document.domain跨子域<br>
                    location.has跨域<br>
                    postMessage实现页面之间通信

                </p>

            </section>
        </section>
        <section>
            <h3>7.参考文献</h3>
        </section>
        <section style="text-align: left;font-size: 25px">
            <p>参考一 :
                <a href="http://kb.cnblogs.com/page/139725/">说说JSON和JSONP，也许你会豁然开朗</a>
            </p>
            <br>
            <p>参考二 :
                <a href="https://www.zhihu.com/question/41430703?from=profile_question_card">古尘师姐在知乎关于Nginx的配置回答</a>
            </p>
            <br>
            <p>参考三 :
                <a href="http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html">&ensp;阮一峰—浏览器同源政策及其规避方法</a>
            </p>
            <p>参考四：
                <a href="https://zhuanlan.zhihu.com/p/28562290">跨域的那些事</a>
            </p>

        </section>
        <section>
            <section>
                <h3>8.更多讨论</h3>
            </section>
            <section>
                <B>怎么选择跨域的方法？</B>
                <p>跨域的方法很多，不同的应用场景我们都可以找到一个最合适的解决方案。</p>
                <p>比如单向的数据请求，我们应该优先选择JSONP或者window.name，</p>
                <p>双向通信优先采取location.hash，</p>
                <p>在未与数据提供方达成通信协议的情况下我们也可以用server proxy的方式来抓取数据。</p>
            </section>
        </section>
        <section>
            <h4>鸣谢</h4>
            <p>感谢大家观看</p>
            <p>感谢 郭健锋 师兄</p>

        </section>

    </div>
</div>

<script src="../lib/reveal/js/head.min.js"></script>
<script src="../lib/reveal/reveal.js"></script>

<script>

    // 以下为常见配置属性的默认值
    // {
    // 	controls: true, // 是否在右下角展示控制条
    // 	progress: true, // 是否显示演示的进度条
    // 	slideNumber: false, // 是否显示当前幻灯片的页数编号，也可以使用代码slideNumber: 'c / t' ，表示当前页/总页数。
    // 	history: false, // 是否将每个幻灯片改变加入到浏览器的历史记录中去
    // 	keyboard: true, // 是否启用键盘快捷键来导航
    // 	overview: true, // 是否启用幻灯片的概览模式，可使用"Esc"或"o"键来切换概览模式
    // 	center: true, // 是否将幻灯片垂直居中
    // 	touch: true, // 是否在触屏设备上启用触摸滑动切换
    // 	loop: false, // 是否循环演示
    // 	rtl: false, // 是否将演示的方向变成RTL，即从右往左
    // 	fragments: true, // 全局开启和关闭碎片。
    // 	autoSlide: 0, // 两个幻灯片之间自动切换的时间间隔（毫秒），当设置成 0 的时候则禁止自动切换，该值可以被幻灯片上的 ` data-autoslide` 属性覆盖
    // 	transition: 'default', // 切换过渡效果，有none/fade/slide/convex/concave/zoom
    // 	transitionSpeed: 'default', // 过渡速度，default/fast/slow
    // 	mouseWheel: true, //是否启用通过鼠标滚轮来切换幻灯片
    // }

    // 初始化幻灯片
    Reveal.initialize({
        history: true,
        dependencies: [
            {src: '../plugin/markdown/marked.js'},
            {src: '../plugin/markdown/markdown.js'},
            {src: '../plugin/notes/notes.js', async: true},
            {
                src: '../plugin/highlight/highlight.js',
                async: true,
                callback: function () {
                    hljs.initHighlightingOnLoad();
                }
            }
        ]
    });
</script>
</body>
</html>
